
#ifndef MSTP_BPDU_H
#define MSTP_BPDU_H

#include "base_types.h"

// ============================================================================

enum BPDU_PORT_ROLE
{
	BPDU_PORT_ROLE_MASTER = 0,
	BPDU_PORT_ROLE_UNKNOWN = 0,
	BPDU_PORT_ROLE_ALT_BACKUP = 1,
	BPDU_PORT_ROLE_ROOT = 2,
	BPDU_PORT_ROLE_DESIGNATED = 3,
};

union BPDU_FLAGS
{
	struct
	{
		unsigned char Tc		: 1;
		unsigned char Proposal	: 1;
		unsigned char PortRole	: 2;
		unsigned char Learning	: 1;
		unsigned char Forwarding: 1;
		unsigned char Agreement	: 1;
	} asCist;
	
	struct
	{
		unsigned char Tc		: 1;
		unsigned char Proposal	: 1;
		unsigned char PortRole	: 2;
		unsigned char Learning	: 1;
		unsigned char Forwarding: 1;
		unsigned char Agreement	: 1;
		unsigned char Master	: 1;
	} asMsti;
	
	struct
	{
		unsigned char Tc		: 1;
		unsigned char Proposal	: 1;
		unsigned char PortRole	: 2;
		unsigned char Learning	: 1;
		unsigned char Forwarding: 1;
		unsigned char Agreement	: 1;
		unsigned char TcAck 	: 1;
	};	
};


struct MSTI_CONFIG_MESSAGE
{
	BPDU_FLAGS	flags;
	BRIDGE_ID	RegionalRootId;
	INV_UINT4	InternalRootPathCost;
	unsigned char BridgePriority;
	unsigned char PortPriority;
	unsigned char RemainingHops;
};

// ============================================================================

struct BPDU_HEADER
{
	INV_UINT2 protocolId;
	unsigned char protocolVersionId;
	unsigned char bpduType;
};

// ============================================================================

// 13.7
struct MST_CONFIG_ID
{
	unsigned char ConfigurationIdentifierFormatSelector;// 1)
	char ConfigurationName [32];						// 2)
	unsigned char RevisionLevel [2];					// 3)
	unsigned char ConfigurationDigest [16];				// 4)
	
	bool operator== (const MST_CONFIG_ID& rhs) const;	
	void Dump (BRIDGE* bridge, int port, int tree) const;
};

// ============================================================================

struct MSTP_BPDU : public BPDU_HEADER
{
	BPDU_FLAGS	cistFlags;				// octet 5
	
	BRIDGE_ID	cistRootId;				// octets 6 to 13
	INV_UINT4	cistExternalPathCost;	// octets 14 to 17
	BRIDGE_ID	cistRegionalRootId;		// octets 18 to 25
	INV_UINT2	cistPortId;				// octets 26 to 27
	
	INV_UINT2	MessageAge;		// octets 28 to 29
	INV_UINT2	MaxAge;			// octets 30 to 31
	INV_UINT2	HelloTime;		// octets 32 to 33
	INV_UINT2	ForwardDelay;	// octets 34 to 35
	
	unsigned char Version1Length;
	INV_UINT2 Version3Length;
	
	MST_CONFIG_ID	mstConfigId;
	
	INV_UINT4		cistInternalRootPathCost;
	BRIDGE_ID		cistBridgeId;
	
	unsigned char	cistRemainingHops;
	
	// MSTI_CONFIG_MESSAGE mstiConfigMessages [0];
};

// ============================================================================

enum VALIDATED_BPDU_TYPE
{
	VALIDATED_BPDU_TYPE_UNKNOWN,
	VALIDATED_BPDU_TYPE_STP_CONFIG,
	VALIDATED_BPDU_TYPE_STP_TCN,
	VALIDATED_BPDU_TYPE_RST,
	VALIDATED_BPDU_TYPE_MST
};

enum VALIDATED_BPDU_TYPE MSTP_GetValidatedBpduType (const unsigned char* _bpdu, int bpduSize);

unsigned int GetBpduPortRole (PORT_ROLE role);

void DumpMstpBpdu (BRIDGE* bridge, int port, int tree, const MSTP_BPDU* bpdu, int indent);
void DumpRstpBpdu (BRIDGE* bridge, int port, int tree, const MSTP_BPDU* bpdu, int indent);

// ============================================================================

#endif
